/**
 * Swagger 数据处理工具类
 * 提供解析和处理 Swagger/OpenAPI 文档的通用方法
 */

export class SwaggerUtils {
    /**
     * 解析定义引用
     * @param {Object} definitions - 定义对象
     * @param {string} refName - 引用名称
     * @param {Set} visited - 已访问的引用集合，防止循环引用
     * @returns {Object|null} 解析后的定义对象
     */
    static resolveDefinition(definitions, refName, visited = new Set()) {
        // 防止循环引用
        if (visited.has(refName)) {
            return { error: 'Circular reference detected' };
        }

        visited.add(refName);

        const definition = definitions[refName];
        if (!definition) {
            return null;
        }

        // 递归解析所有引用
        const resolved = JSON.parse(JSON.stringify(definition));

        if (resolved.properties) {
            for (const [propName, propValue] of Object.entries(resolved.properties)) {
                if (propValue.$ref) {
                    const nestedRefName = propValue.$ref.split('/').pop();
                    resolved.properties[propName] = this.resolveDefinition(definitions, nestedRefName, new Set(visited));
                } else if (propValue.type === 'array' && propValue.items && propValue.items.$ref) {
                    const nestedRefName = propValue.items.$ref.split('/').pop();
                    propValue.items = this.resolveDefinition(definitions, nestedRefName, new Set(visited));
                }
            }
        }

        return resolved;
    }

    /**
     * 提取入参 (针对 OpenAPI 3.0.1)
     * @param {Object} method - 方法对象
     * @param {Object} swaggerDoc - Swagger 文档对象
     * @returns {Object|null} 提取的入参对象
     */
    static extractInputParams(method, swaggerDoc) {
        const definitions = swaggerDoc.components && swaggerDoc.components.schemas || {};

        // OpenAPI 3.0 使用 requestBody 而不是 parameters
        if (!method.parameters && !method.requestBody) {
            return null;
        }

        // 构造一个包含所有参数的虚拟对象
        const paramsObject = {
            type: 'object',
            properties: {},
            required: []
        };

        // 处理路径参数、查询参数等
        if (method.parameters) {
            method.parameters.forEach(param => {
                if (param.in === 'body' && param.schema) {
                    // 处理body参数
                    if (param.schema.$ref) {
                        const refName = param.schema.$ref.split('/').pop();
                        const resolved = this.resolveDefinition(definitions, refName);
                        if (resolved && resolved.properties) {
                            paramsObject.properties = {
                                ...paramsObject.properties,
                                ...resolved.properties
                            };
                            if (resolved.required) {
                                paramsObject.required = [
                                    ...paramsObject.required,
                                    ...resolved.required
                                ];
                            }
                        }
                    } else if (param.schema.properties) {
                        // 如果body参数有properties，直接使用
                        paramsObject.properties = {
                            ...paramsObject.properties,
                            ...param.schema.properties
                        };
                        if (param.schema.required) {
                            paramsObject.required = [
                                ...paramsObject.required,
                                ...param.schema.required
                            ];
                        }
                    } else {
                        // 否则将参数作为一个属性
                        paramsObject.properties[param.name] = param.schema;
                        if (param.required) {
                            paramsObject.required.push(param.name);
                        }
                    }
                } else if (param.in !== 'body') {
                    // 处理query、path、header等参数
                    paramsObject.properties[param.name] = {
                        type: param.type || 'string',
                        description: param.description || ''
                    };
                    if (param.required) {
                        paramsObject.required.push(param.name);
                    }
                }
            });
        }

        // 处理 OpenAPI 3.0 格式
        if (method.requestBody) {
            const content = method.requestBody.content;
            if (!content) {
                // 即使没有content，也要返回已有的参数
                if (Object.keys(paramsObject.properties).length > 0) {
                    return paramsObject;
                }
                return null;
            }

            // 查找 application/json 类型的内容
            const jsonContent = content['application/json'];
            if (!jsonContent) {
                // 即使没有json content，也要返回已有的参数
                if (Object.keys(paramsObject.properties).length > 0) {
                    return paramsObject;
                }
                return null;
            }

            const schema = jsonContent.schema;
            if (!schema) {
                // 即使没有schema，也要返回已有的参数
                if (Object.keys(paramsObject.properties).length > 0) {
                    return paramsObject;
                }
                return null;
            }

            // 处理引用类型，将其属性合并到当前对象中
            if (schema.$ref) {
                const refName = schema.$ref.split('/').pop();
                const resolvedSchema = this.resolveDefinition(definitions, refName);
                // 将请求体参数添加到paramsObject中
                paramsObject.properties['requestBody'] = resolvedSchema;
                if (method.requestBody.required) {
                    paramsObject.required.push('requestBody');
                }
            } else if (schema.type === 'array' && schema.items) {
                // 处理数组类型的请求体
                let arrayItemsSchema;
                if (schema.items.$ref) {
                    const refName = schema.items.$ref.split('/').pop();
                    arrayItemsSchema = this.resolveDefinition(definitions, refName);
                } else {
                    arrayItemsSchema = schema.items;
                }
                // 将数组类型的请求体参数添加到paramsObject中
                paramsObject.properties['requestBody'] = {
                    type: 'array',
                    items: arrayItemsSchema,
                    description: 'Request body as array'
                };
                if (method.requestBody.required) {
                    paramsObject.required.push('requestBody');
                }
            } else if (schema.properties) {
                // 如果schema有properties，处理每个属性
                // 创建一个新的schema对象来存储处理后的属性
                const processedSchema = {
                    type: 'object',
                    properties: {},
                    required: schema.required || []
                };

                // 直接处理properties中的每个属性，包括引用类型
                for (const [propName, propValue] of Object.entries(schema.properties)) {
                    if (propValue.$ref) {
                        // 解析引用类型
                        const refName = propValue.$ref.split('/').pop();
                        const resolved = this.resolveDefinition(definitions, refName);
                        processedSchema.properties[propName] = resolved;
                    } else {
                        processedSchema.properties[propName] = propValue;
                    }
                }
                
                // 将请求体参数添加到paramsObject中
                paramsObject.properties['requestBody'] = processedSchema;
                if (method.requestBody.required) {
                    paramsObject.required.push('requestBody');
                }
            } else {
                // 其他情况直接使用schema
                paramsObject.properties['requestBody'] = schema;
                if (method.requestBody.required) {
                    paramsObject.required.push('requestBody');
                }
            }
        }

        // 如果有参数则返回，否则返回null
        if (Object.keys(paramsObject.properties).length > 0) {
            return paramsObject;
        }
        return null;
    }

    /**
     * 提取出参 (针对 OpenAPI 3.0.1)
     * @param {Object} method - 方法对象
     * @param {Object} swaggerDoc - Swagger 文档对象
     * @returns {Object|null} 提取的出参对象
     */
    static extractOutputParams(method, swaggerDoc) {
        const definitions = swaggerDoc.components && swaggerDoc.components.schemas || {};

        if (!method.responses) {
            return null;
        }

        const response200 = method.responses['200'];
        if (!response200) {
            return null;
        }

        // 处理 OpenAPI 3.0 格式
        if (response200.content) {
            const contentTypes = Object.keys(response200.content);

            // 查找 */* 或 application/json 类型的内容
            const contentType = contentTypes.find(type => type === '*/*' || type === 'application/json') || contentTypes[0];
            if (!contentType) {
                return null;
            }

            const content = response200.content[contentType];
            if (!content) {
                return null;
            }

            const schema = content.schema;
            if (!schema) {
                return null;
            }

            // 处理引用类型
            if (schema.$ref) {
                const responseRefName = schema.$ref.split('/').pop();
                return this.resolveDefinition(definitions, responseRefName);
            } else {
                return schema;
            }
        }

        // 处理 Swagger 2.0 格式
        if (!response200.schema) {
            return null;
        }

        // 处理不同类型的响应
        if (response200.schema.$ref) {
            const responseRefName = response200.schema.$ref.split('/').pop();
            return this.resolveDefinition(definitions, responseRefName);
        } else {
            return response200.schema;
        }
    }

    /**
     * 从响应定义中提取data字段
     * @param {Object} responseDefinition - 响应定义对象
     * @param {Object} definitions - 定义对象
     * @returns {Object|null} 提取的data字段对象
     */
    static extractDataFromResponse(responseDefinition, definitions) {
        if (!responseDefinition) {
            return null;
        }

        // 提取data字段下的数据
        if (!responseDefinition.properties) {
            return responseDefinition;
        }

        if (!responseDefinition.properties.data) {
            // 如果没有data字段，返回整个响应定义
            return responseDefinition;
        }

        const dataSchema = responseDefinition.properties.data;

        if (dataSchema.$ref) {
            // 对象类型引用
            const dataRefName = dataSchema.$ref.split('/').pop();
            return this.resolveDefinition(definitions, dataRefName);
        } else if (dataSchema.type === 'array' && dataSchema.items && dataSchema.items.$ref) {
            // 数组类型引用
            const dataRefName = dataSchema.items.$ref.split('/').pop();
            return this.resolveDefinition(definitions, dataRefName);
        } else {
            // 基本类型或其他类型
            return dataSchema;
        }
    }

    /**
     * 解析所有字段
     * @param {Object} swaggerData - Swagger 数据对象
     * @returns {Array} 解析后的字段数组
     */
    static parseAllFields(swaggerData) {
        let allFields = [];

        // 获取definitions/schemas
        const definitions = swaggerData.definitions || swaggerData.components && swaggerData.components.schemas || {};

        // 遍历所有路径
        Object.keys(swaggerData.paths).forEach((path) => {
            const pathData = swaggerData.paths[path];

            // 遍历所有方法
            Object.keys(pathData).forEach((method) => {
                const operation = pathData[method];
                const tags = operation.tags || [];
                const moduleName = tags[0] || "未分类";

                // 解析入参
                if (operation.parameters) {
                    operation.parameters.forEach((param) => {
                        if (
                            param.schema &&
                            param.schema.type === "object" &&
                            param.schema.properties
                        ) {
                            // 解析对象类型的参数属性
                            this.parseProperties(
                                param.schema.properties,
                                `${param.name}`,
                                moduleName,
                                `${method.toUpperCase()} ${path}`,
                                param.schema.required || [],
                                0,
                                new Set(),
                                allFields
                            );
                        } else if (param.schema && param.schema.$ref) {
                            // 解析引用类型参数
                            const refName = param.schema.$ref.split('/').pop();
                            const refSchema = this.resolveDefinition(definitions, refName);
                            if (refSchema && refSchema.properties) {
                                this.parseProperties(
                                    refSchema.properties,
                                    `${param.name}`,
                                    moduleName,
                                    `${method.toUpperCase()} ${path}`,
                                    refSchema.required || [],
                                    0,
                                    new Set(),
                                    allFields
                                );
                            }
                        } else {
                            // 简单参数
                            allFields.push({
                                name: param.name,
                                description: param.description || "",
                                interface: `${method.toUpperCase()} ${path}`,
                                module: moduleName,
                            });
                        }
                    });
                }

                // 解析入参 (OpenAPI 3.0 requestBody)
                if (operation.requestBody) {
                    const content = operation.requestBody.content;
                    if (content) {
                        const jsonContent = content['application/json'];
                        if (jsonContent) {
                            const schema = jsonContent.schema;
                            if (schema) {
                                // 处理引用类型，将其属性合并到当前对象中
                                if (schema.$ref) {
                                    const refName = schema.$ref.split('/').pop();
                                    const resolvedSchema = this.resolveDefinition(definitions, refName);
                                    if (resolvedSchema && resolvedSchema.properties) {
                                        // 直接处理引用类型的属性
                                        for (const [propName, propValue] of Object.entries(resolvedSchema.properties)) {
                                            if (propValue.$ref) {
                                                // 解析嵌套引用类型
                                                const nestedRefName = propValue.$ref.split('/').pop();
                                                const nestedResolved = this.resolveDefinition(definitions, nestedRefName);
                                                allFields.push({
                                                    name: propName,
                                                    description: propValue.description || nestedResolved.description || nestedResolved.title || propName,
                                                    interface: `${method.toUpperCase()} ${path}`,
                                                    module: moduleName
                                                });
                                                
                                                // 解析嵌套引用类型的属性
                                                if (nestedResolved && nestedResolved.properties) {
                                                    this.parseProperties(
                                                        nestedResolved.properties,
                                                        propName,
                                                        moduleName,
                                                        `${method.toUpperCase()} ${path}`,
                                                        nestedResolved.required || [],
                                                        0,
                                                        new Set(),
                                                        allFields
                                                    );
                                                }
                                            } else {
                                                allFields.push({
                                                    name: propName,
                                                    description: propValue.description || propValue.title || "",
                                                    interface: `${method.toUpperCase()} ${path}`,
                                                    module: moduleName
                                                });
                                                
                                                // 处理嵌套对象
                                                if (propValue.type === "object" && propValue.properties) {
                                                    this.parseProperties(
                                                        propValue.properties,
                                                        propName,
                                                        moduleName,
                                                        `${method.toUpperCase()} ${path}`,
                                                        propValue.required || [],
                                                        0,
                                                        new Set(),
                                                        allFields
                                                    );
                                                } else if (propValue.type === "array" && propValue.items) {
                                                    if (propValue.items.properties) {
                                                        // 对象数组
                                                        this.parseProperties(
                                                            propValue.items.properties,
                                                            `${propName}[]`,
                                                            moduleName,
                                                            `${method.toUpperCase()} ${path}`,
                                                            propValue.items.required || [],
                                                            0,
                                                            new Set(),
                                                            allFields
                                                        );
                                                    } else if (propValue.items.$ref) {
                                                        // 引用类型数组
                                                        const arrayRefName = propValue.items.$ref.split('/').pop();
                                                        const arrayResolved = this.resolveDefinition(definitions, arrayRefName);
                                                        if (arrayResolved && arrayResolved.properties) {
                                                            this.parseProperties(
                                                                arrayResolved.properties,
                                                                `${propName}[]`,
                                                                moduleName,
                                                                `${method.toUpperCase()} ${path}`,
                                                                arrayResolved.required || [],
                                                                0,
                                                                new Set(),
                                                                allFields
                                                            );
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                } else if (schema.properties) {
                                    // 直接处理properties中的每个属性，包括引用类型
                                    for (const [propName, propValue] of Object.entries(schema.properties)) {
                                        if (propValue.$ref) {
                                            // 解析引用类型
                                            const refName = propValue.$ref.split('/').pop();
                                            const resolved = this.resolveDefinition(definitions, refName);
                                            allFields.push({
                                                name: propName,
                                                description: propValue.description || resolved.description || resolved.title || propName,
                                                interface: `${method.toUpperCase()} ${path}`,
                                                module: moduleName
                                            });
                                            
                                            // 解析引用类型的属性
                                            if (resolved && resolved.properties) {
                                                this.parseProperties(
                                                    resolved.properties,
                                                    propName,
                                                    moduleName,
                                                    `${method.toUpperCase()} ${path}`,
                                                    resolved.required || [],
                                                    0,
                                                    new Set(),
                                                    allFields
                                                );
                                            }
                                        } else {
                                            allFields.push({
                                                name: propName,
                                                description: propValue.description || propValue.title || "",
                                                interface: `${method.toUpperCase()} ${path}`,
                                                module: moduleName
                                            });
                                            
                                            // 处理嵌套对象
                                            if (propValue.type === "object" && propValue.properties) {
                                                this.parseProperties(
                                                    propValue.properties,
                                                    propName,
                                                    moduleName,
                                                    `${method.toUpperCase()} ${path}`,
                                                    propValue.required || [],
                                                    0,
                                                    new Set(),
                                                    allFields
                                                );
                                            } else if (propValue.type === "array" && propValue.items) {
                                                if (propValue.items.properties) {
                                                    // 对象数组
                                                    this.parseProperties(
                                                        propValue.items.properties,
                                                        `${propName}[]`,
                                                        moduleName,
                                                        `${method.toUpperCase()} ${path}`,
                                                        propValue.items.required || [],
                                                        0,
                                                        new Set(),
                                                        allFields
                                                    );
                                                } else if (propValue.items.$ref) {
                                                    // 引用类型数组
                                                    const arrayRefName = propValue.items.$ref.split('/').pop();
                                                    const arrayResolved = this.resolveDefinition(definitions, arrayRefName);
                                                    if (arrayResolved && arrayResolved.properties) {
                                                        this.parseProperties(
                                                            arrayResolved.properties,
                                                            `${propName}[]`,
                                                            moduleName,
                                                            `${method.toUpperCase()} ${path}`,
                                                            arrayResolved.required || [],
                                                            0,
                                                            new Set(),
                                                            allFields
                                                        );
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                // 解析出参
                if (operation.responses) {
                    const response200 = operation.responses["200"];
                    if (response200) {
                        // OpenAPI 3.0 格式
                        if (response200.content) {
                            const contentTypes = Object.keys(response200.content);
                            const contentType = contentTypes.find(type => type === '*/*' || type === 'application/json') || contentTypes[0];
                            if (contentType) {
                                const content = response200.content[contentType];
                                if (content) {
                                    const schema = content.schema;
                                    if (schema) {
                                        let responseSchema = schema;
                                        if (schema.$ref) {
                                            const refName = schema.$ref.split('/').pop();
                                            responseSchema = this.resolveDefinition(definitions, refName);
                                        }
                                        
                                        // 尝试提取data字段下的属性
                                        if (responseSchema && responseSchema.properties) {
                                            if (responseSchema.properties.data && responseSchema.properties.data.properties) {
                                                this.parseProperties(
                                                    responseSchema.properties.data.properties,
                                                    "data",
                                                    moduleName,
                                                    `${method.toUpperCase()} ${path}`,
                                                    responseSchema.properties.data.required || [],
                                                    0,
                                                    new Set(),
                                                    allFields
                                                );
                                            } else {
                                                // 直接解析顶层属性
                                                this.parseProperties(
                                                    responseSchema.properties,
                                                    "",
                                                    moduleName,
                                                    `${method.toUpperCase()} ${path}`,
                                                    responseSchema.required || [],
                                                    0,
                                                    new Set(),
                                                    allFields
                                                );
                                            }
                                        }
                                    }
                                }
                            }
                        } 
                        // Swagger 2.0 格式
                        else if (response200.schema) {
                            let responseSchema = response200.schema;
                            if (responseSchema.$ref) {
                                const refName = responseSchema.$ref.split('/').pop();
                                responseSchema = this.resolveDefinition(definitions, refName);
                            }
                            
                            // 尝试提取data字段下的属性
                            if (responseSchema && responseSchema.properties) {
                                if (responseSchema.properties.data && responseSchema.properties.data.properties) {
                                    this.parseProperties(
                                        responseSchema.properties.data.properties,
                                        "data",
                                        moduleName,
                                        `${method.toUpperCase()} ${path}`,
                                        responseSchema.properties.data.required || [],
                                        0,
                                        new Set(),
                                        allFields
                                    );
                                } else {
                                    // 直接解析顶层属性
                                    this.parseProperties(
                                        responseSchema.properties,
                                        "",
                                        moduleName,
                                        `${method.toUpperCase()} ${path}`,
                                        responseSchema.required || [],
                                        0,
                                        new Set(),
                                        allFields
                                    );
                                }
                            }
                        }
                    }
                }
            });
        });

        // 过滤掉描述为空的字段
        allFields = allFields.filter(field => field.description && field.description.trim() !== "");
        
        return allFields;
    }

    /**
     * 解析属性
     * @param {Object} properties - 属性对象
     * @param {string} prefix - 前缀
     * @param {string} moduleName - 模块名称
     * @param {string} interfaceName - 接口名称
     * @param {Array} requiredFields - 必填字段数组
     * @param {number} level - 递归层级
     * @param {Set} visitedRefs - 已访问引用集合
     * @param {Array} allFields - 所有字段数组
     */
    static parseProperties(
        properties,
        prefix,
        moduleName,
        interfaceName,
        requiredFields,
        level = 0,
        visitedRefs = new Set(),
        allFields
    ) {
        // 防止过深的递归
        if (level > 10) {
            console.warn('Max recursion level reached, stopping to prevent infinite loop');
            return;
        }
        
        Object.keys(properties).forEach((key) => {
            const prop = properties[key];
            const fullName = prefix ? `${prefix}.${key}` : key;

            // 获取字段描述，优先使用description，其次使用title
            const description = prop.description || prop.title || "";

            allFields.push({
                name: fullName,
                description: description,
                interface: interfaceName,
                module: moduleName,
            });

            // 解析嵌套对象
            let nestedProperties = null;
            if (prop.properties) {
                nestedProperties = prop.properties;
            } else if (prop.$ref) {
                // 解析引用类型
                const definitions = swaggerData.definitions || swaggerData.components && swaggerData.components.schemas || {};
                const refName = prop.$ref.split('/').pop();
                
                // 检查循环引用
                if (!visitedRefs.has(refName)) {
                    visitedRefs.add(refName);
                    const refSchema = this.resolveDefinition(definitions, refName, new Set());
                    if (refSchema && refSchema.properties) {
                        nestedProperties = refSchema.properties;
                    }
                    visitedRefs.delete(refName);
                }
            }

            if (nestedProperties) {
                // 递归解析对象属性
                this.parseProperties(
                    nestedProperties,
                    fullName,
                    moduleName,
                    interfaceName,
                    prop.required || [],
                    level + 1,
                    new Set(visitedRefs),
                    allFields
                );
            } else if (
                prop.type === "array" &&
                prop.items
            ) {
                // 处理数组类型
                if (prop.items.properties) {
                    // 对象数组
                    this.parseProperties(
                        prop.items.properties,
                        `${fullName}[]`,
                        moduleName,
                        interfaceName,
                        prop.items.required || [],
                        level + 1,
                        new Set(visitedRefs),
                        allFields
                    );
                } else if (prop.items.$ref) {
                    // 引用类型数组
                    const definitions = swaggerData.definitions || swaggerData.components && swaggerData.components.schemas || {};
                    const refName = prop.items.$ref.split('/').pop();
                    
                    // 检查循环引用
                    if (!visitedRefs.has(refName)) {
                        visitedRefs.add(refName);
                        const refSchema = this.resolveDefinition(definitions, refName, new Set());
                        if (refSchema && refSchema.properties) {
                            this.parseProperties(
                                refSchema.properties,
                                `${fullName}[]`,
                                moduleName,
                                interfaceName,
                                refSchema.required || [],
                                level + 1,
                                new Set(visitedRefs),
                                allFields
                            );
                        }
                        visitedRefs.delete(refName);
                    }
                }
            }
        });
    }
}


